package com.xiaozhen.jt809.utils;

import com.xiaozhen.jt809.constant.JT809MessageConstant;
import com.xiaozhen.jt809.domain.JT809MessageHeader;
import com.xiaozhen.jt809.domain.JT809MessageInfo;

/**
 * HISTORY
 *
 * @author zhenweisheng
 * @date 2021/9/14 13:27
 * @description:
 */
public class PacketUtil {


    public static JT809MessageInfo getMessageInfo(byte[] data) {
        JT809MessageInfo messageInfo = new JT809MessageInfo();
        int offset = 0;
        //头标
        int headFlag = data[0];
        offset += 1;
        messageInfo.setHeadFlag(headFlag);
        //数据头
        JT809MessageHeader messageHeader = new JT809MessageHeader();
        int msgLength = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 4));
        offset += 4;
        messageHeader.setMsgLength(msgLength);
        int msgSn = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 4));
        offset += 4;
        messageHeader.setMsgSn(msgSn);
        int msgId = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 2));
        offset += 2;
        messageHeader.setMsgId(msgId);
        int msgGnssCenterId = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 4));
        offset += 4;
        messageHeader.setMsgGnssCenterId(msgGnssCenterId);
        byte[] versionFlag = ByteArrayUtil.subBytes(data, offset, 3);
        offset += 3;
        messageHeader.setVersionFlag(versionFlag);
        //是否加密  0不加密 1加密
        int encryptFlag = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 1));
        offset += 1;
        messageHeader.setEncryptFlag(encryptFlag);
        int encryptKey = ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(data, offset, 4));
        offset += 4;
        messageHeader.setEncryptKey(encryptKey);
        //系统UTC时间
//        byte[] time = ByteArrayUtil.subBytes(data, offset, 8);
//        offset += 8;
//        messageHeader.setTime(time);
        messageInfo.setMessageHeader(messageHeader);
        //数据体
        int dataLen = getMsgBodyLen(msgLength, offset);
        if (dataLen > 0) {
            byte[] messageBody = ByteArrayUtil.subBytes(data, offset, dataLen);
            //如果加密的话  解密
            if (encryptFlag == 1) {
                messageBody = EncryptUtil.encrypt(2398L, 4500L, 678678L,
                        encryptKey, messageBody);
            }
            offset += dataLen;
            messageInfo.setMessageBody(messageBody);
        }
        byte[] crcCode = ByteArrayUtil.subBytes(data, offset, 2);
        offset += 2;
        messageInfo.setCrcCode(crcCode);
        int endFlag = data[data.length - 1];
        offset += 1;
        messageInfo.setEndFlag(endFlag);
        return messageInfo;
    }

    /**
     * 获取数据体长度
     *
     * @param msgLength    数据长度
     * @param headerLength 头标和数据头的长度
     * @return
     */
    public static int getMsgBodyLen(int msgLength, int headerLength) {
        //完整数据长度 == （数据长度 = 头标识 + 数据头 + 数据体 + 尾标识）- 头标识 - 数据头 - CRC - 尾标识
        return msgLength - headerLength - 2 - 1;
    }

    /**
     * 校验消息头标识
     *
     * @param data
     * @return
     */
    public static boolean checkHeadFlag(byte[] data) {
        return JT809MessageConstant.HEAD_FLAG == data[0];
    }

    /**
     * 校验消息尾标识
     *
     * @param data
     * @return
     */
    public static boolean checkTailFlag(byte[] data) {
        return JT809MessageConstant.END_FLAG == data[data.length - 1];
    }

    /**
     * 解析经纬度
     * @param data
     * @return
     */
    public static double parseLonOrLat(byte[] data){
        double r =  ByteArrayUtil.bytes2int(data) / Math.pow(10,6);
        return Double.parseDouble(String.format("%.6f",r));
    }

    /**
     * 获取数据包完整长度
     * @return
     */
    public static int getPacketLen(byte[] realBytes){
        //完整数据长度 == （数据长度 = 头标识 + 数据头 + 数据体 + 尾标识）
        return ByteArrayUtil.bytes2int(ByteArrayUtil.subBytes(realBytes,1,4));
    }

    /**
     * 校验数据体
     * @return
     */
    public static boolean checkPacket(byte[] readDatas){
        //校验数据头 防止递归调用失败
        if(!checkHeadFlag(readDatas) || !checkTailFlag(readDatas)){
            return false;
        }
        return true;
    }
}
